import 'package:backend.core/logger/log_level.dart';
import 'package:backend.core/logger/log_printer.dart';
import 'package:logger/logger.dart' as pkg;

class Logger {
  static final _instance = Logger._internal();

  static LogLevel _logLevel = LogLevel.error;

  static late pkg.Logger _pkgLogger;

  static LogLevel get logLevel => _logLevel;

  static set logLevel(LogLevel logLevel) {
    if (_logLevel == logLevel) {
      return;
    }

    _logLevel = logLevel;

    _pkgLogger = _createPkgLogger(
      logLevel: _logLevel,
    );
  }

  Logger._internal() {
    _pkgLogger = _createPkgLogger(
      logLevel: _logLevel,
    );
  }

  factory Logger() {
    return _instance;
  }

  void v(String message) {
    _pkgLogger.v(message);
  }

  void i(String message) {
    _pkgLogger.i(message);
  }

  void w(String? message, [dynamic error, StackTrace? stackTrace]) {
    _pkgLogger.w(message, error, stackTrace);
  }

  void e(String? message, [dynamic error, StackTrace? stackTrace]) {
    _pkgLogger.e(message, error, stackTrace);
  }

  void close() {
    _pkgLogger.close();
  }
}

pkg.Level _createPkgLogLevel({
  required LogLevel logLevel,
}) {
  switch (logLevel) {
    case LogLevel.verbose:
      return pkg.Level.verbose;
    case LogLevel.debug:
      return pkg.Level.debug;
    case LogLevel.info:
      return pkg.Level.info;
    case LogLevel.warning:
      return pkg.Level.warning;
    case LogLevel.error:
      return pkg.Level.error;
    case LogLevel.wtf:
      return pkg.Level.wtf;
    case LogLevel.nothing:
      return pkg.Level.nothing;
  }
}

pkg.Logger _createPkgLogger({
  required LogLevel logLevel,
}) {
  final pkgLogLevel = _createPkgLogLevel(
    logLevel: logLevel,
  );

  return pkg.Logger(
    printer: LogPrinter(
      methodCount: 0,
      errorMethodCount: 40,
      colors: true,
      stackTraceBeginIndex: 0,
    ),
    level: pkgLogLevel,
    output: pkg.ConsoleOutput(),
    filter: pkg.ProductionFilter(),
  );
}
